#include<stdio.h>
#include<sys/ioctl.h>
#include"terminal_cmd.h"
#include"terminal_ptty.h"
#include"terminal_console.h"
#include"terminal_cursor.h"

cmd_man_t *cmdman=NULL;


void printf_cmdline()
{
    shell_printf(cmdman->cmd_line);
}

int do_buildin_cmd(char *cmd)
{
    if(!memcmp(cmd,"cls",strlen("cls")))
    {
        dprintf("clean screen");
        console.clear();
        write(pty.fd_master,'\n',1); //end current comand
        return 0;
    }
}

char *cmd_argv[MAX_ARG_NUM]={0};

//check cmdline added '\n' and send to console execute
int cmdline_check()
{
    if(cmdman->cmd_line[0]!=0)
    {
        cmd_buff_insert();
    }

    if(do_buildin_cmd(cmdman->cmd_line)<0)
    {
        dprintf("do builin command error\n");
    }
    
    //add '\n' at the end
    cmdman->cmd_line[cmdman->cmd_len]='\n';
    cmdman->cmd_len++;
    cmdman->cmd_line[cmdman->cmd_len]='\0'; //string eof 

    //dprintf("[debug] write master: data %x\n",cmdman->cmd_line);

    //write to window and wait console read
    write(pty.fd_master,cmdman->cmd_line,cmdman->cmd_len);
    
    //reset arg
    cmdman->cmd_pos=cmdman->cmd_line;
    cmdman->cmd_len=0;

    //clear cmd line and continue read new 
    memset(cmdman->cmd_line,0,CMD_LINE_LEN);
    return 0;
}

void cmd_buff_insert()
{
    cmd_buff_t *cmdbuff=&cmdman->cmd_buff[0];

    int i;
    //check if cmd data has been insert to buffer,if true retrun 
    for(i=0;i<CMD_BUFF_NUM;i++)
    {
        if(cmdbuff->flags>0)
        {
            if(!strcmp(cmdbuff->cmdbuff,cmdman->cmd_line))
                return ;
        }
        cmdbuff++;
    }

    //select next buffer to insert
    cmdbuff=&cmdman->cmd_buff[cmdman->next_cmd_buff];
    memset(cmdbuff->cmdbuff,0,CMD_LINE_LEN);
    memcpy(cmdbuff->cmdbuff,cmdman->cmd_line,CMD_LINE_LEN);
    cmdbuff->flags=1;

    //point to next
    cmdman->next_cmd_buff++;
    cmdman->cur_cmd_buff=cmdman->next_cmd_buff;
    //loop buffer 
    if(cmdman->next_cmd_buff>=CMD_BUFF_NUM)
        cmdman->next_cmd_buff=0;
}

void cmd_buff_copy()
{
    cmd_buff_t *cmdbuff=&cmdman->cmd_buff[cmdman->cur_cmd_buff];
    memset(cmdman->cmd_line,0,CMD_LINE_LEN);
    memcpy(cmdman->cmd_line,cmdbuff->cmdbuff,CMD_LINE_LEN);
}

/** select history command
 * @dir: select directory: -1 up 1 down
 * */
void cmd_buff_select(int dir)
{
    int temp;
    cmd_buff_t *cmdbuff;
    if(dir==-1) //get last history cmd
    {
        temp=cmdman->cur_cmd_buff-1;
        if(temp<0)
            temp=CMD_BUFF_NUM-1;
    }
    else if(dir==1) //get next history cmd
    {
        temp=cmdman->cur_cmd_buff+1;
        if(temp>=CMD_BUFF_NUM)
        {
            temp=0;
        }
    }
    else 
        return -1;

    cmdbuff=&cmdman->cmd_buff[temp];
    if(cmdbuff->flags>0)
    {
        //select cmd
        cmdman->cur_cmd_buff=temp;

        int cmdlen=strlen(cmdman->cmd_line);
        int cwdlen=strlen(cmdman->cwd_cache);
        int total=cmdlen+cwdlen+1;
        int lines=DIV_ROUND_UP(total,console.columns);
        //if is multilines,cursor up move lines-1 lines
        if(lines>1)
        {
            cursor.y-=lines-1;
        } 
        //clear lines
        int y=cursor.y*console.text_height;
        console.clear_area(0,y,console.width,(lines+1)*console.text_height);
        //clear char
        console_set_chars(' ',total,0,cursor.y);
        //move to line head
        move_cursor(0,cursor.y);
        //printf promt and cmd line
        cmd_buff_copy();
        printf_cmdline();
        //figure cmd line length and cur char position
        cmdman->cmd_len=strlen(cmdman->cmd_line);
        cmdman->cmd_pos=cmdman->cmd_line+cmdman->cmd_len;
        return 0;
    }
    return -1;
}

//set command line context
int cmdline_set(char *buff,int bufflen)
{
    //figure original command occupy lines
    int cmdlen=strlen(cmdman->cmd_line);
    int cwdlen=strlen(cmdman->cwd_cache);
    int total=cmdlen+cwdlen+1;
    int lines=DIV_ROUND_UP(total,console.columns);
    if(lines>1) //above 1 lines,cursor move up
        cursor.y-=lines-1;
    //get cursor lines position 
    int y=cursor.y*console.text_height;
    //clear data
    console.clear_area(0,y,console.width,(lines+1)*console.text_height);
    //clear char data
    console_set_chars(' ',total,0,cursor.y);
    //move cursor to line head
    move_cursor(0,cursor.y);
    //printf content
    memset(cmdman->cmd_line,0,CMD_LINE_LEN);
    memcpy(cmdman->cmd_line,buff,CMD_LINE_LEN);
    printf_cmdline();
    //figure cmdline legth and position
    cmdman->cmd_len=strlen(cmdman->cmd_line);
    cmdman->cmd_pos=cmdman->cmd_line+cmdman->cmd_len;

    //window refresh update
    terminal_window_update(0,0,console.width,console.height);
    return -1;
}

int terminal_cmdman_init()
{
    cmdman=malloc(SIZE_CMD_MAX);
    if(!cmdman)
    {
        dprintf("[terminal] cmd man alloc failed\n");
        return -1;
    }
    memset(cmdman,0,SIZE_CMD_MAX);


    memset(cmdman->cwd_cache,0,MAX_PATH_LEN);
    getcwd(cmdman->cwd_cache,MAX_PATH_LEN);
    memset(cmdman->cmd_line,0,CMD_LINE_LEN);

    cmdman->cur_cmd_buff=0;
    cmdman->next_cmd_buff=0;

    cmdman->cmd_pos=cmdman->cmd_line;
    cmdman->cmd_len=0;

    return 0;
}

void exit_cmdman()
{
    free(cmdman);
}
